package BitCreekTracker;

import BitCreekLib.Host;
import BitCreekLib.TorrentMetaDati;

import javax.net.ssl.SSLSocket;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Map;

/**
 * Created by Ivan Litsvinenka e Emanuele Ricci
 * Date: 30-lug-2009
 * Time: 15.56.59
 */
public class TrackerTCPWorker implements Runnable {

    private final SSLSocket clientSocket;

    /**
     * Metodo privato che in base al nome del torrent prelieva la lista dei Peers relativa a quel torrent.
     *
     * @param torrentName Il nome del torrent
     * @return null Se non esiste il descrittore del torrent nell'Hash Table o se non ci sono Peers connessi per quel torrent
     */
    private ArrayList<Host> getPeersList ( String torrentName ) {
        if ( TrackerServices.tht.containsKey ( torrentName ) ) {
            return TrackerServices.tht.get ( torrentName ).getPeersList ();
        } else {
            return new ArrayList<Host> ();
        }

    }
    
    private void handleEx( Exception e ) {
    	
        InetAddress touse = clientSocket.getInetAddress();
         if( touse.isLoopbackAddress () ) {
             try {
                 touse = InetAddress.getLocalHost();
             } catch ( UnknownHostException e1 ) {
                 e1.printStackTrace ();
             }
         }
         int c, size;
         TrackerPeer temp = new TrackerPeer(new Host (touse, 0));
         for (Map.Entry<String, TorrentMetaDati> tmd: TrackerServices.tht.entrySet() ) {
             size = tmd.getValue().getPeers().size();
             for ( c = 0; c < size; c++  ) {
            	 try {
            		 if ( temp.equals(tmd.getValue().getPeers().get(c)) ) {
                     
                    	 tmd.getValue().getPeers().remove(c);
                     
                    	 break;
            		 }
            	 } catch ( ArrayIndexOutOfBoundsException ex ) {}
             }
         }
    }

    public TrackerTCPWorker( SSLSocket clientSocket ) {
        this.clientSocket = clientSocket;
    }

    public void run() {

        ArrayList<Host> peersList;
        String torrentName;

        try {
            ObjectOutputStream output = new ObjectOutputStream ( clientSocket.getOutputStream () );
            ObjectInputStream input = new ObjectInputStream ( clientSocket.getInputStream () );

            while( true ) {
            	try {
	                torrentName = ( String ) input.readObject ();
	                peersList = getPeersList ( torrentName );
	                output.writeObject ( peersList );
            	} catch ( SocketException e  ) {
            		handleEx( e );
            		return;
                } catch ( EOFException e) {
                	handleEx( e );
                	return;
					
				} catch (ClassNotFoundException e) {
					return;
				}

          }

        } catch (IOException e) {
			e.printStackTrace();
		} finally {
            try {
            	
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }



    }
}
